package com.hm.hall.commons.util;

import com.alibaba.fastjson.JSON;
import com.hm.hall.commons.constans.GameConstans;
import com.hm.hall.commons.constans.po.GeoDomain;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.List;

/**
 * 地理位置工具
 * Created by Administrator on 2016/4/27.
 */
public class LocationUtils {
    public static double X_PI = 3.14159265358979324 * 3000.0 / 180.0;
    private static Logger log = Logger.getLogger(LocationUtils.class);
    private static double EARTH_RADIUS = 6378.137;

    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * 获得距离(单位米) , 仅为度有问题的话,返回 距离:  -1
     *
     * @param locationA 经纬度A 例: 43.850857,125.331928
     * @param locationB 经纬度B 例: 43.899063,125.33279
     * @return
     */
    public static int getDistanceRice(String locationA, String locationB) {
        if (StringUtils.isBlank(locationA) || StringUtils.isBlank(locationB)) {
            return -1;
        }

        String lA[] = locationA.split(",");
        String lB[] = locationB.split(",");
        double jieguo = getDistance(Double.valueOf(lA[0]), Double.valueOf(lA[1]), Double.valueOf(lB[0]), Double.valueOf(lB[1]));

        double jieguo2 = jieguo * 1000;
        return new Double(Math.round(jieguo2)).intValue();
    }

    /**
     * 获得距离(单位 公里)
     *
     * @param locationA 经纬度A 例: 43.850857,125.331928
     * @param locationB 经纬度B 例: 43.899063,125.33279
     * @return
     */
    public static int getDistanceKm(String locationA, String locationB) {
        return getDistanceRice(locationA, locationB) / 1000;
    }

    /**
     * 获得智能距离字符串 (大于1000米显示 X公里 反之显示 X米)
     *
     * @param locationA 经纬度A 例: 43.850857,125.331928
     * @param locationB 经纬度B 例: 43.899063,125.33279
     */
    public static String getDistance(String locationA, String locationB) {
        int rice = getDistanceRice(locationA, locationB);
        if (rice > 1000) {
            return rice + " 公里";
        } else {
            return rice + " 米";
        }
    }

    public static double getDistance(double y1, double x1, double y2, double x2) {
        double radLat1 = rad(y1);
        double radLat2 = rad(y2);
        double a = radLat1 - radLat2;
        double b = rad(x1) - rad(x2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        return s;
    }


    /*
        X_PI=3.14159265358979324 * 3000.0 / 180.0;
        function baiduTomars(baidu_point){
            var mars_point={lon:0,lat:0};
            var x=baidu_point.lon-0.0065;
            var y=baidu_point.lat-0.006;
            var z=Math.sqrt(x*x+y*y)- 0.00002 * Math.sin(y * X_PI);
            var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
            mars_point.lon=z * Math.cos(theta);
            mars_point.lat=z * Math.sin(theta);
            return mars_point;
        }
     */

    /**
     * loc 坐标转地址文本
     *
     * @param location latitude + "," + longtitude
     * @return GeoDomain 合理的地址对象 or null
     */
    public static GeoDomain geocoderV2(String location) {

        String latitude = location.split(",")[0];
        String longtitude = location.split(",")[1];
        //0.0坐标，不用查询
        if (0 == Double.valueOf(latitude) || 0 == Double.valueOf(longtitude)) {
            GeoDomain geo = new GeoDomain();
            geo.setStatus(-1);
            return geo;
        }

        GeoDomain poi = null;
        DefaultHttpClient httpclient = HttpClientUtils.getClient();
        DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(
                1, true);
        httpclient.setHttpRequestRetryHandler(retryHandler);
        httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);

        HttpResponse response;
        HttpPost httpost = new HttpPost("http://api.map.baidu.com/geocoder/v2/");
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        // 固定值
        nvps.add(new BasicNameValuePair("ak", GameConstans.BAIDU_MAP_AK));
        nvps.add(new BasicNameValuePair("output", "json"));
        // baidu接口有点变态。。反查location=22.549922,113.940585 是反的
        String loc2 = latitude + "," + longtitude;
        nvps.add(new BasicNameValuePair("location", loc2));
        try {
            httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
            response = httpclient.execute(httpost);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, "UTF-8");
                poi = JSON.parseObject(result, GeoDomain.class);
                if (poi != null && poi.status == 0) {
                    return poi;
                } else {
                    log.error("解析地址数据失败,返回码及信息为:" + result);
                }
            }

        } catch (Exception e) {
            log.error(e);
        }
        return poi;
    }

    /**
     * 火星坐标转百度
     *
     * @param latitude
     * @param longtitude
     * @return String  latitude + "," + longtitude
     */
    public static String marsToBaidu(double latitude, double longtitude) {
        double x = longtitude, y = latitude;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * X_PI);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * X_PI);
        double baiduLon = z * Math.cos(theta) + 0.0065;
        double baiduLat = z * Math.sin(theta) + 0.006;
        return baiduLat + "," + baiduLon;
    }


}
